﻿#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QSettings>
#include <QNetworkInterface>
#include <QRegularExpression>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->window()->setWindowTitle("TCPtools");

    ui->sent->setEnabled(false);


    server = new QTcpServer(this);
    socket = new QTcpSocket(this);

    ui->recvData->setPlainText("Developed by RQY.\n2021-10-15 v1.0\n");

    {
        {
            QStringList list = {"None", "CR", "LF", "CR&LF"};
            ui->endString->addItems(list);
        }
    }

    {
        // 初始化文件
        //路径为程序路径下，文件不存在会自行创建
        QString iniFilePath = QCoreApplication::applicationDirPath() + "/config.ini";
        //新建QSettings类，路径+格式
        QSettings settings(iniFilePath,QSettings::IniFormat);
        //设置编码，使支持中文
        settings.setIniCodec("UTF-8");

        ui->targetAddress->setText(settings.value("ADDRESS/targetAddress").toString());
        ui->portInput->setText(settings.value("ADDRESS/portInput").toString());
        ui->endString->setCurrentIndex(settings.value("ADDRESS/endString").toString().toInt());
    }

    {
        connect(server,SIGNAL(newConnection()),this,SLOT(newconnected()));

        connect(ui->sent,SIGNAL(clicked(bool)),this,SLOT(sendData()));

        connect(ui->toggleServer,SIGNAL(clicked(bool)),this,SLOT(toggleServer()));
        connect(ui->toggleClient,SIGNAL(clicked(bool)),this,SLOT(toggleClient()));

        connect(ui->clearRecv, SIGNAL(clicked(bool)),this, SLOT(clearData()));
        connect(ui->clearSent , SIGNAL(clicked(bool)),this, SLOT(clearData()));
    }
}

MainWindow::~MainWindow()
{
    {
        // 初始化文件
        //路径为程序路径下，文件不存在会自行创建
        QString iniFilePath = QCoreApplication::applicationDirPath() + "/config.ini";
        //新建QSettings类，路径+格式
        QSettings settings(iniFilePath,QSettings::IniFormat);
        //设置编码，使支持中文
        settings.setIniCodec("UTF-8");
        settings.setValue("ADDRESS/targetAddress",ui->targetAddress->text());
        settings.setValue("ADDRESS/portInput",ui->portInput->text());
        settings.setValue("ADDRESS/endString",ui->endString->currentIndex());
    }
    delete ui;
}

void MainWindow::newconnected()
{
    if(server->hasPendingConnections()){    //  如果服务端有一个待处理的连接，就返回真，否则返回假
        socket = server->nextPendingConnection();   //将下一个挂起的连接作为已连接的qtcsocket对象返回。
        if(!socket->isValid()){ //套接字是否有效
            return;
        }
        ui->connectStatus->setText("connect");
        ui->sent->setEnabled(true);


        connect(socket,SIGNAL(readyRead()),this,SLOT(recvData()));
        connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()));
    }
}

void MainWindow::sendData()
{
    QString str = ui->sentData->toPlainText();

    switch (ui->endString->currentIndex()) {
    case 1:str+='\r';break;
    case 2:str+='\n';break;
    case 3:str+="\r\n";break;
    }

    socket->write(str.toStdString().c_str(),str.length());
}

void MainWindow::recvData()
{
    QByteArray str = socket->readAll();
    QString data = ui->recvData->toPlainText();
    data+=str;
    ui->recvData->setPlainText(data);
    ui->recvData->moveCursor(QTextCursor::End);
}

void MainWindow::disconnected()
{
    ui->connectStatus->setText("disconnect");
    ui->sent->setEnabled(false);
}

void MainWindow::toggleServer()    // 启动服务器
{
    static bool isRunning = false;
    if(!isRunning){

        // 端口8888
        int port;
        {bool portNAN;
            port = ui->portInput->text().toInt(&portNAN);
            if(!portNAN)
                port=8888;
        }

        ui->toggleServer->setText("Close Server");
        ui->toggleClient->setEnabled(false);

        // 显示服务器启动
        ui->recvData->append("Server setup.");
        updateAddress();

        isRunning = true;

        if(!server->listen(QHostAddress::AnyIPv4,quint16(port))){   // 监听
            return;
        }

    }else{
        server->close();
        socket->close();

        ui->toggleServer->setText("Open Server");
        ui->toggleClient->setEnabled(true);

        // 服务器关闭
        ui->recvData->append("Server close.\n");

        isRunning = false;
    }
}

void MainWindow::toggleClient()    // 启动客户端
{
    static bool isRunning = false;
    if(!isRunning){

        QString ip = ui->targetAddress->text(); // 地址
        int port = ui->portInput->text().toInt(); // 端口

        socket->connectToHost(ip, port);

        ui->recvData->append("Connect...");

        if(socket->waitForConnected(1000))
        {
            ui->connectStatus->setText("connect");
            ui->sent->setEnabled(true);

            connect(socket,SIGNAL(readyRead()),this,SLOT(recvData()));
            connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()));

            ui->toggleClient->setText("Close Client");
            ui->toggleServer->setEnabled(false);

            ui->recvData->append("Connect success.\n");

            isRunning = true;
        }
        else{
            ui->recvData->append("Connect fail.\n");
        }
    }else{
        socket->disconnectFromHost();
        disconnect();

        ui->toggleClient->setText("Open Client");
        ui->toggleServer->setEnabled(true);

        ui->recvData->append("Disconnect.\n");

        isRunning = false;
    }
}

void MainWindow::updateAddress()   // 更新地址
{
    {
        QString address, out;

        out = "Self available address list:\n";

        QRegularExpression re;
        QRegularExpressionMatch match;
        re.setPattern("\\d+\\.\\d+\\.\\d+\\.\\d+");
        for(int i=0;i<QNetworkInterface().allAddresses().count();i++){
            address = QNetworkInterface().allAddresses().at(i).toString();
            match = re.match(address);
            if(match.hasMatch()){
                out+=address;
                out+='\n';
            }
        }

        ui->recvData->append(out);
    }
}

void MainWindow::clearData() // 清空数据
{
    QPushButton *clearButton = qobject_cast<QPushButton*>(sender());
    if(clearButton==ui->clearRecv)
        ui->recvData->clear();
    else if(clearButton==ui->clearSent)
        ui->sentData->clear();
}
